MediaPlayer Error (1,-2147479552), Error (-38,0)

  |  

播放视频时,采用TextureView+MediaPlayer的方案,一切都照旧。可是,在红米3s上却出现了问题。当第一个页面加载了自定义的播放器后,再打开有播放器的第二个页面时,第二个页面的播放器就不能正常播放了。提示如下错误:

MediaPlayer: Error (1,-2147479552), Error (-38,0), stop called in state 0

播放视频时,采用TextureView+MediaPlayer的方案,一切都照旧。可是,在红米3s上却出现了问题。当第一个页面加载了自定义的播放器后,再打开有播放器的第二个页面时,第二个页面的播放器就不能正常播放了,一直在输出错误的log,如下所示。

01-10 11:07:36.259 9688-9699/com.mediaplayer.demo E/MediaPlayer: error (1, -2147479552)
01-10 11:07:36.260 9688-9688/com.mediaplayer.demo E/MediaPlayer: Error (1,-2147479552)
01-10 11:07:36.262 9688-9729/com.mediaplayer.demo E/MediaPlayer: error (1, -38)
01-10 11:07:36.685 9688-9688/com.mediaplayer.demo E/MediaPlayer: stop called in state 1
01-10 11:07:36.685 9688-9688/com.mediaplayer.demo E/MediaPlayer: error (-38, 0)
01-10 11:07:36.685 9688-9688/com.mediaplayer.demo E/MediaPlayer: Error (1,-38)
01-10 11:07:37.047 9688-9688/com.mediaplayer.demo E/MediaPlayer: stop called in state 0
01-10 11:08:00.632 9688-9688/com.mediaplayer.demo E/MediaPlayer: start called in state 0
01-10 11:08:00.632 9688-9688/com.mediaplayer.demo E/MediaPlayer: error (-38, 0)
01-10 11:08:00.633 9688-9688/com.mediaplayer.demo E/MediaPlayer: start called in state 0
01-10 11:08:00.633 9688-9688/com.mediaplayer.demo E/MediaPlayer: error (-38, 0)
01-10 11:08:00.639 9688-9688/com.mediaplayer.demo E/MediaPlayer: Error (-38,0)
01-10 11:08:01.087 9688-9688/com.mediaplayer.demo E/MediaPlayer: stop called in state 0
01-10 11:08:01.088 9688-9688/com.mediaplayer.demo E/MediaPlayer: Error (-38,0)
01-10 11:08:01.426 9688-9688/com.mediaplayer.demo E/MediaPlayer: stop called in state 0

没道理啊,测试了其他近十几款不同牌子和型号的手机都没问题,而且红米3都没问题,但是红米3s就是不行。为何呢?开始分析日志。

查询错误:Mediaplayer start called in state 0。Stack Overflow上有给出解决办法的,就是在start()之前要调用MediaPlayer.prepraeAsync(),可是prepare已经在设置视频源时调用过了,没有解决,此方案不行。

吭哧吭哧……经过多次的测试与分析发现,对于红米3S等低配手机,当内存中存在多个TextureView时,如果在当前界面onPause()时,会调用onSurfaceTextureDestroyed(),导致下一个界面在初始化MediaPlayer绑定TextureView时出现error (1, -2147479552)的报错,因此需要在onSurfaceTextureDestroyed()时调用将MediaPlayer和Surface解除关系,在SurfaceView调用Update时再关联。另外,关于Surface的valid有些机型也表现的很诡异,按理说在onSurfaceTextureAvailable(SurfaceTexture)回调后获取Surface应该是可以立即使用的,但是有些机型就是一直提示invalid的报错,在此也一定做了兼容处理。详细解决方案见下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
Surface mSurface;
/**
* 标记SurfaceTexture是否销毁。对于红米3S等低配手机,在当前界面onPause()时,会调用
* onSurfaceTextureDestroyed(),导致下一个界面在初始化MediaPlayer时出现
* error (1, -2147479552)的报错,因此需要在onSurfaceTextureDestroyed()时调用
* 将MediaPlayer和Surface解除关系,在SurfaceView调用Update时再关联。
*/
private boolean isSurfaceTextureDestroyed = false;
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
Log.d(TAG, "onSurfaceTextureAvailable: ");
mSurface = new Surface(surfaceTexture);
// 当Surface有效后再绑定MediaPlayer
Observable.just(true)
.retryUntil(() -> mSurface.isValid())
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(b ->{
if (mMediaPlayer != null) {
Log.d(TAG, "onSurfaceTextureAvailable: setSurface " + mSurface.isValid());
mMediaPlayer.setSurface(mSurface);
}
});
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
Log.d(TAG, "onSurfaceTextureDestroyed--" + this.hashCode());
isSurfaceTextureDestroyed = true;
if (mMediaPlayer != null) {
mMediaPlayer.setSurface(null);
}
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
if (isSurfaceTextureDestroyed) {
Log.d(TAG, "onSurfaceTextureUpdated--" + this.hashCode());
// 当前页面获取焦点后判断Surface时候销毁,已销毁则重新绑定
mMediaPlayer.setSurface(new Surface(surface));
isSurfaceTextureDestroyed = false;
}
}
文章目录
,